import { relationalStore } from '@kit.ArkData';
import { JSON } from '@kit.ArkTS';

export default class rdbManager {
  static context = null
  static rdbStore = null
  static storename = ""

  static async createStore(context, storename = "rdbstore2.db") {
    this.storename = storename
    return new Promise((resolve, reject) => {
      this.context = context
      const store_config = {
        name: storename, securityLevel: 1
      }
      relationalStore.getRdbStore(this.context, store_config).then((rdbStore) => {
        this.rdbStore = rdbStore
        console.log("_:_%%%%create store " + storename + " success")
        resolve(storename)
      })
        .catch((e) => {
          console.log("_:_%%%%create store " + storename + " fail " + e.code + e.message);
          resolve(false);
        })
    })
  }

  static async createTable(tablename, schema = " (id integer primary key autoincrement,name string,vec string)") {
    return new Promise((resolve, reject) => {
      let sqlstring = "create table  " + tablename + schema
      this.rdbStore.executeSql(sqlstring)
        .then(() => {
          console.log("_:_%%%%create table " + tablename + " success")
          resolve(tablename)
        })
        .catch((e) => {
          console.log("_:_%%%%create table " + tablename + " fail " + e.code + e.message);
          resolve(false);
        })
    })
  }

  static async insert(tableName, valueBucket): Promise<string> {
    return new Promise((resolve, reject) => {
      this.rdbStore.insert(tableName, valueBucket)
        .then((rowid) => {
          // if (tableName == "node") {
          //   console.log("_:_%%%%insert success:" + tableName + " with content" + valueBucket.content + " with rowid " +
          //   JSON.stringify(rowid))
          // } else {
          console.log("_:%%%%insert success:" + tableName + " with item content " + JSON.stringify(valueBucket) +
            " with rowid " +
          JSON.stringify(rowid))
          // }
          resolve(JSON.stringify(rowid))
        })
        .catch((e) => {
          console.log("_:_%%%%1 insert fail " + JSON.stringify(e),tableName,JSON.stringify(valueBucket))
          resolve(e.message)
        })
    })
  }

  static async query(tableName) {
    let columns
    switch (tableName) {
      case "tasknv":
      case "appnv":
        columns = ["id", "name", 'vec']
        break
      case "tasksteps":
        columns = ["id", "name", "steps", "vec"]
        break
      case "node":
        columns = ["parent", "id", "content", "children", "entries", "vec"]
        break
      case "notes":
        columns = ["id", "name", "content"]
      case "jsonnode":
        columns = ["id", "content"]
        break
      case "convs":
        columns = ["id", "content", "role"]
        break
      case "ocrimage":
        columns = ["id", "content", "path", "vec"]
        break
      case "tasks":
        columns = ["id", "name", "task", "steps", "gparams", "historycalls"]
        break
    }
    console.log("_:%%%%resultset aboutToquery", tableName)
    return new Promise((resolve, reject) => {
      let predicate = new relationalStore.RdbPredicates(tableName)
      this.rdbStore.query(predicate, columns)
        .then((resultSet) => {
          console.log("_:%%%%resultset column names: " + resultSet.columnNames)
          console.log("_:%%%%resultset column count: " + resultSet.columnCount)
          this.dealWithResultSet(tableName, resultSet).then((reslv) => {
            resolve(reslv)
          })
        }).catch((e) => {
        console.log("_:_%%%%query failed" + e.message)
        resolve(false)
      })
    })
  }

  static async deleteTableItem(predicates) {
    try {
      let rows = await this.rdbStore.delete(predicates)
      console.log("Delete rows: " + rows)
    } catch (e) {
      console.info("Delete failed, err: " + JSON.stringify(e))
    }
  }

  static async findTableItem(tableName, predicates) {
    try {
      let resultSet = await this.rdbStore.query(predicates)
      console.log("_:%%%%resultset column names: " + resultSet.columnNames)
      console.log("_:%%%%resultset column count: " + resultSet.columnCount)
      let resultList = await this.dealWithResultSet(tableName, resultSet) as any[]
      return resultList
    } catch (e) {
      console.error("_:_%%%%findTableItem fail" + JSON.stringify(e))
      return []
    }
  }

  static async deleteStore() {
    let storename = this.storename
    return new Promise((resolve, reject) => {
      relationalStore.deleteRdbStore(this.context, storename, (err) => {
        if (err) {
          console.info("_:_%%%%Failed to delete " + storename + " err: " + err)
          reject(storename)
          return
        }
        console.log("_:_%%%%Deleted " + storename + " successfully.")
        resolve(storename)
      })
    })
  }

  static async update(valuebucket, predicates) {
    return new Promise((resolve) => {
      if (this.rdbStore != null) {
        (this.rdbStore as relationalStore.RdbStore).update(valuebucket, predicates,
          relationalStore.ConflictResolution.ON_CONFLICT_REPLACE, (err, rows) => {
            if (err) {
              console.error(`_:_%%%%Updated failed, code is ${err.code},message is ${err.message}`,
                JSON.stringify(valuebucket), JSON.stringify(predicates));
              resolve(false)
              return;
            }
            console.info(`_:%%%%Updated row count: ${rows}`);
            resolve(true)
          })
      }
    })
  }

  static async clearStore() {
    await this.deleteStore()
    await this.createStore(this.context, this.storename)
  }

  static async dealWithResultSet(tablename, resultSet) {
    return new Promise((resolve, reject) => {
      console.log("_:%%%%dealing with resultset")
      let count = resultSet.rowCount;
      if (count === 0 || typeof count === "string") {
        console.log("_:_%%%%query no result")
        resolve([])
      } else {
        resultSet.goToFirstRow();
        const result = [];
        for (let i = 0; i < count; i++) {
          switch (tablename) {
            case "appnv":
            case "tasknv":
              let tmp0 = {
                'id': 0, 'name': "", vec: undefined
              }
              tmp0.id = resultSet.getDouble(resultSet.getColumnIndex('id'))
              tmp0.name = resultSet.getString(resultSet.getColumnIndex('name'))
              tmp0.vec = resultSet.getString(resultSet.getColumnIndex('vec'))
              result[i] = tmp0;
              break
            case "tasksteps":
              let tmp1 = {
                'id': 0,
                'name': "",
                "steps": "",
                vec: undefined
              }
              tmp1.id = resultSet.getDouble(resultSet.getColumnIndex('id'))
              tmp1.name = resultSet.getString(resultSet.getColumnIndex('name'))
              tmp1.steps = resultSet.getString(resultSet.getColumnIndex("steps"))
              tmp1.vec = resultSet.getString(resultSet.getColumnIndex('vec'))
              result[i] = tmp1;
              break
            case "node":
              let tmp2 = {
                id: 0,
                content: "",
                parent: 0,
                children: "",
                entries: "",
                vec: "",
                parentL: {},
                childrenL: []
              }
              tmp2.id = resultSet.getDouble(resultSet.getColumnIndex('id'))
              tmp2.content = resultSet.getString(resultSet.getColumnIndex('content'))
              tmp2.parent = resultSet.getDouble(resultSet.getColumnIndex('parent'))
              tmp2.children = resultSet.getString(resultSet.getColumnIndex('children'))
              tmp2.entries = resultSet.getString(resultSet.getColumnIndex('entries'))
              tmp2.vec = resultSet.getString(resultSet.getColumnIndex('vec'))
              result[i] = tmp2;
              break
            case "jsonnode":
              let tmp3 = {
                id: 0,
                content: "",
              }
              tmp3.id = resultSet.getDouble(resultSet.getColumnIndex("id"))
              tmp3.content = resultSet.getString(resultSet.getColumnIndex("content"))
              result[i] = tmp3;
              break;
            case "convs":
              let tmp4 = {
                id: 0,
                content: "",
                role: ""
              }
              tmp4.id = resultSet.getDouble(resultSet.getColumnIndex("id"))
              tmp4.content = resultSet.getString(resultSet.getColumnIndex("content"))
              tmp4.role = resultSet.getString(resultSet.getColumnIndex("role"))
              result[i] = tmp4;
              break;
            case "ocrimage":
              let tmp5 = {
                id: 0,
                content: "",
                path: "",
                vec: ""
              }
              tmp5.id = resultSet.getDouble(resultSet.getColumnIndex("id"))
              tmp5.content = resultSet.getString(resultSet.getColumnIndex("content"))
              tmp5.path = resultSet.getString(resultSet.getColumnIndex("path"))
              tmp5.vec = resultSet.getString(resultSet.getColumnIndex('vec'))
              result[i] = tmp5
              break;
            case "tasks":
              let tmp6 = {
                id: 0,
                name: "",
                task: "",
                steps: "",
                gparams: "",
                historycalls: ""
              }
              tmp6.id = resultSet.getDouble(resultSet.getColumnIndex("id"))
              tmp6.name = resultSet.getString(resultSet.getColumnIndex("name"))
              tmp6.task = resultSet.getString(resultSet.getColumnIndex("task"))
              tmp6.steps = resultSet.getString(resultSet.getColumnIndex("steps"))
              tmp6.gparams = resultSet.getString(resultSet.getColumnIndex("gparams"))
              tmp6.historycalls = resultSet.getString(resultSet.getColumnIndex("historycalls"))
              result[i] = tmp6
              break;
            case "notes":
              let tmp7 = {
                id: 0,
                name: "",
                content:""
              }
              tmp7.id = resultSet.getDouble(resultSet.getColumnIndex("id"))
              tmp7.name = resultSet.getString(resultSet.getColumnIndex("name"))
              tmp7.content = resultSet.getString(resultSet.getColumnIndex("content"))
              result[i] = tmp7
              break;
          }
          resultSet.goToNextRow();
        }
        console.log("_:%%%% result from db" + JSON.stringify(result.reverse()))
        resolve(result)
      }
    })
  }
}